package dawnland03.model.entity;

import dawnland03.model.action.impl.ActionFactory;
import dawnland03.model.action.Action;
import dawnland03.model.action.parameter.ActionOutputParam;
import dawnland03.model.task.*;
import dawnland03.model.quest.*;
import dawnland03.model.task.impl.MoveToTask;
import dawnland03.model.item.ItemType;
import dawnland03.model.item.Item;
import org.apache.log4j.Logger;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * User: Petru Obreja (obrejap@yahoo.com)
 * Date: Jan 19, 2010
 * Time: 10:18:11 PM
 */
public class EntityBrain implements Runnable, QuestObserver {
    private final Entity entity;
    private final SimpleDateFormat simpleDateFormat;

    private LinkedList<Quest> quests;

    private static Logger logger = Logger.getLogger(EntityBrain.class.getName());

    public EntityBrain(Entity entity) {
        this.entity = entity;
        simpleDateFormat = new SimpleDateFormat("HH:mm:ss-SSS");
        quests = new LinkedList<Quest>(); //todo: use a synchronized collection
    }

    public void run() {
        System.out.println(entity + "'s thread:" + Thread.currentThread().getName());
        Action initAction = ActionFactory.createInitAction(entity);
        initAction.act();

        QuestManager.getQuestManager().attach(QuestType.GATHER_COAL, this);
        QuestManager.getQuestManager().attach(QuestType.MOVE, this);
        while (true) {
            Quest currentQuest = null;
            try {
                synchronized (this) {
                    if (quests.size() == 0) {
                        wait();
                    }
                    currentQuest = quests.removeFirst();
                    System.out.println(simpleDateFormat.format(new Date()) + " Entity " + entity + " gets quests:" + currentQuest);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Quest quest = currentQuest;
            if (quest.getQuestType() == QuestType.GATHER_COAL) {
                System.out.println(simpleDateFormat.format(new Date()) + " Entity " + entity + " starts to work.");
                final Integer quantity = (Integer) quest.getParam(QuestParam.QUANTITY);
                /*GroupTask groupTask = new GroupTask(quest.getQuestType().toString(), entity);
                for (int i = 1; i <= quantity; i++) {
                    Action action = ActionFactory.createGatherCoalAction(entity);
                    BaseTask baseTask = new BaseTask("baseTask", entity, action);
                    groupTask.addTask(baseTask);
                }
                groupTask.execute();
                groupTask.waitForTaskToEnd();*/

                Action action = ActionFactory.createGatherCoalAction(entity);
                TaskCondition taskCondition = new TaskCondition() {

                    public void isTaskCompleted(Task currentTask) {
                        Map<ItemType, Set<Item>> items = (Map<ItemType, Set<Item>>) currentTask.getParentTask().getOutputParameters().getOutputParameter(ActionOutputParam.ITEM);
                        Set<Item> coalQuantity = items.get(ItemType.COAL);
//                        return (coalQuantity.size() >= quantity) ? TaskConditionReturn.END : TaskConditionReturn.REPEATE;
                        if (coalQuantity.size() < quantity) {
                            //duplicate the current task add it to parent's tasks
                            currentTask.getParentTask().duplicateTaskAndAddFirst(currentTask);
                        }

                    }
                };
                BaseTask baseTask = new BaseTask("baseTask", entity, action);
                baseTask.addTaskConditionAfterTaskStatus(TaskStatus.FINISHED, taskCondition);
                GroupTask groupTask = new GroupTask("gatherTask", entity);
                groupTask.addTask(baseTask);
                groupTask.executeTask();
                groupTask.waitForTaskToEnd();
                if (logger.isDebugEnabled()) {
                    logger.debug("Entity " + entity + " ended his work.");
                }
            } else if (quest.getQuestType() == QuestType.MOVE) {
                System.out.println(simpleDateFormat.format(new Date()) + " Entity " + entity + " starts to move.");
                Integer destionationMatrixCellId = (Integer) quest.getParam(QuestParam.DESTINATION);
                MoveToTask moveToTask = new MoveToTask(entity, destionationMatrixCellId);
                moveToTask.executeTask();
                moveToTask.waitForTaskToEnd();
                System.out.println(simpleDateFormat.format(new Date()) + " Entity " + entity + " ends to move.");
            }
        }
    }

    public synchronized void notify(Quest quest) {
        quests.add(quest);
        this.notify();
    }
}
